package edu.cornell.cs4740.wsd.predictions;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import edu.cornell.cs4740.wsd.parsing.TrainingData;

public class BaselinePredictor implements Predictor {
//	private static final int NUM_SENSES = 5;
	Map<String, List<Boolean>> classificationMap;
	
	public BaselinePredictor(Map<String, List<TrainingData>> trainingData) {
		classificationMap = new HashMap<String, List<Boolean>>();


		
		// for every word we find the n most used senses where n is the
		// average of the number of senses each word has
		
		for(String word : trainingData.keySet()) {
			List<TrainingData> trainingDataForWord = trainingData.get(word);
			
			List<Boolean> classifier = new ArrayList<Boolean>();
			int numSenses = trainingDataForWord.get(0).getSenseUsage().size();
			for(int x = 0; x < numSenses; x++) {
				classifier.add(Boolean.FALSE);
			}
			
			int totalNumberOfSenses = 0;
			for(TrainingData td : trainingDataForWord) {
				List<Boolean> senses = td.getSenseUsage();
				for(Boolean sense : senses) {
					if(Boolean.TRUE.equals(sense)) {
						totalNumberOfSenses++;
					}
				}
			}
			double averageNumberOfSenses = ((double) totalNumberOfSenses) / ((double) trainingDataForWord.size());
			//System.out.println(averageNumberOfSenses);
			
			int numOfSensesToUse = (int) Math.round(averageNumberOfSenses);
			List<Integer> senseCount = new ArrayList<Integer>(5);
			
			// get the sense counts
			for(TrainingData td : trainingDataForWord) {
				List<Boolean> senses = td.getSenseUsage();
//				System.out.println(senses.toString());
				for(int x = 0; x < numSenses; x++) {
					senseCount.add(new Integer(0));
				}
				for(int x = 0; x < numSenses; x++) {
					if(Boolean.TRUE.equals(senses.get(x))) {

	//						System.out.println(senses.size());
							int sc = senseCount.get(x).intValue();
							sc++;
							senseCount.set(x, new Integer(sc));
					}
				}
			}
			
			
			// go through each sense count to see if it is in the top n
			// set to True if it is
			List<Integer> sortedSenseIndexes = new ArrayList<Integer>();
			for(int x = 0; x < senseCount.size(); x++) {
				int largestIndex = 0;
				for(int i = 0; i < numSenses; i++) {
					if(senseCount.get(i) > senseCount.get(largestIndex)) {
						largestIndex = i;
					}
				}
				
				sortedSenseIndexes.add(new Integer(largestIndex));
				senseCount.remove(largestIndex);	
			}
			
			//System.out.println(numOfSensesToUse);
			for(int x = 0; x < numOfSensesToUse; x++) {
				Integer senseIndexToSetTrue = sortedSenseIndexes.get(x);
				classifier.set(senseIndexToSetTrue.intValue(), Boolean.TRUE);
			}
			
			classificationMap.put(word, classifier);
			
			
		}
	}
	
	@Override
	public List<Boolean> predict(TrainingData testData) {
		
		List<Boolean> classifier = classificationMap.get(testData.getWord().getWord());
		if(classifier == null) {
			classifier = new ArrayList<Boolean>();
			for(int x = 0; x < testData.getSenseUsage().size(); x++) {
				classifier.add(Boolean.FALSE);
			}
		}
		
		return classifier;
	}

}
